//
//  FlutterBoostAgent.swift
//  FlutterBoostIOSDemo
//
//  Created by wangliang on 2024/4/23.
//

import UIKit
import flutter_boost

@objcMembers
public class FlutterBoostAgent: NSObject {
    
    public static let flutterMainPage = "flutter/mainPage"
    public static let flutterCalendarPage = "flutter/calendarPage"
    
    public static let nativeTestPage = "native/TestPage"
    
    public static let shared = FlutterBoostAgent()
    
    private var navigationController: UINavigationController?
    
    ///用来存返回 flutter 侧返回结果的表
    var resultTable: Dictionary<String,([AnyHashable: Any]?)->Void> = [:]
    
    public func setup(application: UIApplication) {
        FlutterBoost.instance().setup(application, delegate: self) { engine in
            guard let messager = engine?.binaryMessenger else { return }
            let methodChannel = FlutterMethodChannel(name: "flutter_boost_demo", binaryMessenger: messager)
            methodChannel.setMethodCallHandler { [weak self] call, result in
                guard let self = self else { return }
                NSLog("WLTest \(call.method)")
                //TODO 通过 result 回调回去
            }
        }
    }
    
    public func openFlutterRoute(_ navigationController: UINavigationController?, options: FlutterBoostRouteOptions) {
        guard let navigationController = navigationController else { return }
        self.navigationController = navigationController
        FlutterBoost.instance().open(options)
    }
    
    
}

extension FlutterBoostAgent: FlutterBoostDelegate {
    
    public func pushNativeRoute(_ pageName: String, arguments: [AnyHashable : Any]?) {
        // Flutter 启动 Native 页面
        if pageName == FlutterBoostAgent.nativeTestPage {
            let vc = TestViewController()
            vc.pageName = pageName
            vc.params = arguments
            self.navigationController?.pushViewController(vc, animated: true)
        }
    }
    
    public func pushFlutterRoute(_ options: FlutterBoostRouteOptions?) {
        guard let options = options, let pageName = options.pageName else { return }
        let flutterVC: FBFlutterViewContainer = WLFlutterBoostViewController()
        flutterVC.setName(pageName, uniqueId: options.uniqueId, params: options.arguments, opaque: options.opaque)
        
        //用参数来控制是push还是pop
        let isPresent = (options.arguments?["isPresent"] as? Bool)  ?? false
        let isAnimated = (options.arguments?["isAnimated"] as? Bool) ?? true

        //对这个页面设置结果
        resultTable[options.pageName] = options.onPageFinished;
        
        //如果是present模式 ，或者要不透明模式，那么就需要以present模式打开页面
        if(isPresent || !options.opaque){
            self.navigationController?.present(flutterVC, animated: isAnimated, completion: nil)
        }else{
            self.navigationController?.pushViewController(flutterVC, animated: isAnimated)
        }
    }
    
    public func popRoute(_ options: FlutterBoostRouteOptions?) {
        guard let options = options else { return }
        //如果当前被present的vc是container，那么就执行dismiss逻辑
        if let vc = self.navigationController?.presentedViewController as? FBFlutterViewContainer,vc.uniqueIDString() == options.uniqueId {

            //这里分为两种情况，由于UIModalPresentationOverFullScreen下，生命周期显示会有问题
            //所以需要手动调用的场景，从而使下面底部的vc调用viewAppear相关逻辑
            if vc.modalPresentationStyle == .overFullScreen {

                //这里手动beginAppearanceTransition触发页面生命周期
                self.navigationController?.topViewController?.beginAppearanceTransition(true, animated: false)

                vc.dismiss(animated: true) {
                    self.navigationController?.topViewController?.endAppearanceTransition()
                }
            } else {
                //正常场景，直接dismiss
                vc.dismiss(animated: true, completion: nil)
            }
        } else {
            self.navigationController?.popViewController(animated: true)
        }
        
        //否则直接执行pop逻辑
        //这里在pop的时候将参数带出,并且从结果表中移除
        if let onPageFinshed = resultTable[options.pageName] {
            onPageFinshed(options.arguments)
            resultTable.removeValue(forKey: options.pageName)
        }
    }
}
